nd608 - Project Personalized Real Estate Agent¶

In [ ]:
# Load environment variables from a .env file. Alternatively you can
# manually set the value of OPENAI_API_KEY on this cell.

from os import environ

try:
    from dotenv import load_dotenv
    load_dotenv()
except ModuleNotFoundError:
    pass

if "OPENAI_API_KEY" not in environ:
    environ["OPENAI_API_KEY"] = "your-openai-api-key"
In [ ]:
import pickle

from io import BytesIO
from json import dumps
from pathlib import Path
from textwrap import dedent

import openai
import requests
import torch

from IPython.display import display, Markdown
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.output_parsers import PydanticOutputParser
from PIL import Image
from pydantic import BaseModel, Field, NonNegativeFloat, NonNegativeInt
from transformers import AutoTokenizer, CLIPProcessor, CLIPModel

from db import get_db, init_db, get_listings_table
from models import RealEstateListingLanceRecord
In [ ]:
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
In [ ]:
device = "cpu"

if torch.cuda.is_available():
    device = "cpu"
elif torch.backends.mps.is_available():
    device = "mps"

Generating Real Estate Listings¶

The purpose of this document is to generate synthetic real estate listings using OpenAI's generative AI APIs. We'll also create a LanceDB attaching embeddings to the generated content.

We'll use LangChain's PromptTemplate, PydanticOutputParser to generate the synthetic real estate listings in a structured format to make it easier to store the information on a table. We'll use the format suggested on the project's instruction:

Neighborhood: Green Oaks
Price: $800,000
Bedrooms: 3
Bathrooms: 2
House Size: 2,000 sqft

Description: Welcome to this eco-friendly oasis nestled in the heart of Green Oaks. This charming 3-bedroom, 2-bathroom home boasts energy-efficient features such as solar panels and a well-insulated structure. Natural light floods the living spaces, highlighting the beautiful hardwood floors and eco-conscious finishes. The open-concept kitchen and dining area lead to a spacious backyard with a vegetable garden, perfect for the eco-conscious family. Embrace sustainable living without compromising on style in this Green Oaks gem.

Neighborhood Description: Green Oaks is a close-knit, environmentally-conscious community with access to organic grocery stores, community gardens, and bike paths. Take a stroll through the nearby Green Oaks Park or grab a cup of coffee at the cozy Green Bean Cafe. With easy access to public transportation and bike lanes, commuting is a breeze.
In [ ]:
class RealEstateListingModelOutput(BaseModel):
    neighborhood: str = Field(description="Name of the neighborhod")
    price: NonNegativeInt = Field(description="List price of the property")
    bedrooms: NonNegativeInt = Field(description="Number of bedrooms of the property")
    bathrooms: NonNegativeFloat | NonNegativeInt = Field(description="Number of bathroom of the property")
    has_solar_panels: bool = Field(description="Whether the property has solar panels fitted")
    description: str = Field(description="Description of the property")
    neighborhood_description: str = Field(description="Description of the neighborhood")


class RealEstateListingsModelOutput(BaseModel):
    listings: list[RealEstateListingModelOutput]


class RealEstateListing(RealEstateListingModelOutput):
    image_bytes: bytes | None = Field(description="Contents of the generated image", default=None)
    
    @property
    def image_as_pil(self):
        return Image.open(BytesIO(self.image_bytes))
In [ ]:
parser = PydanticOutputParser(pydantic_object=RealEstateListingsModelOutput)
print(parser.get_format_instructions())
The output should be formatted as a JSON instance that conforms to the JSON schema below.

As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.

Here is the output schema:
```
{"$defs": {"RealEstateListingModelOutput": {"properties": {"neighborhood": {"description": "Name of the neighborhod", "title": "Neighborhood", "type": "string"}, "price": {"description": "List price of the property", "minimum": 0, "title": "Price", "type": "integer"}, "bedrooms": {"description": "Number of bedrooms of the property", "minimum": 0, "title": "Bedrooms", "type": "integer"}, "bathrooms": {"anyOf": [{"minimum": 0.0, "type": "number"}, {"minimum": 0, "type": "integer"}], "description": "Number of bathroom of the property", "title": "Bathrooms"}, "has_solar_panels": {"description": "Whether the property has solar panels fitted", "title": "Has Solar Panels", "type": "boolean"}, "description": {"description": "Description of the property", "title": "Description", "type": "string"}, "neighborhood_description": {"description": "Description of the neighborhood", "title": "Neighborhood Description", "type": "string"}}, "required": ["neighborhood", "price", "bedrooms", "bathrooms", "has_solar_panels", "description", "neighborhood_description"], "title": "RealEstateListingModelOutput", "type": "object"}}, "properties": {"listings": {"items": {"$ref": "#/$defs/RealEstateListingModelOutput"}, "title": "Listings", "type": "array"}}, "required": ["listings"]}
```
In [ ]:
prompt = PromptTemplate(
    template=dedent("""\
        You are a writer and a real estate expert with extensive
        knowledge of the terminolgy and a capable of writing lengthy,
        easy to read and factual descriptions of properties.

        Generate {num_listings} listings of imaginary real estate
        properties. The description of the property should include detailed
        mentions of the property's features like the number of bedrooms and
        bathrooms. The description of the property should include details
        about the exterior as well. The description of the property should
        contain 3 sentences. Include both upper-middle class and lower
        income neighborhoods. The neighborhood income level should be
        consistent with the property. Include a few fixer-upper properties.
    """) + "\n{format_instructions}",
    input_variables=["num_listings"],
    partial_variables={
        "format_instructions": parser.get_format_instructions
    },
)
In [ ]:
print(prompt.format(num_listings=15))
You are a writer and a real estate expert with extensive
knowledge of the terminolgy and a capable of writing lengthy,
easy to read and factual descriptions of properties.

Generate 15 listings of imaginary real estate
properties. The description of the property should include detailed
mentions of the property's features like the number of bedrooms and
bathrooms. The description of the property should include details
about the exterior as well. The description of the property should
contain 3 sentences. Include both upper-middle class and lower
income neighborhoods. The neighborhood income level should be
consistent with the property. Include a few fixer-upper properties.

The output should be formatted as a JSON instance that conforms to the JSON schema below.

As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.

Here is the output schema:
```
{"$defs": {"RealEstateListingModelOutput": {"properties": {"neighborhood": {"description": "Name of the neighborhod", "title": "Neighborhood", "type": "string"}, "price": {"description": "List price of the property", "minimum": 0, "title": "Price", "type": "integer"}, "bedrooms": {"description": "Number of bedrooms of the property", "minimum": 0, "title": "Bedrooms", "type": "integer"}, "bathrooms": {"anyOf": [{"minimum": 0.0, "type": "number"}, {"minimum": 0, "type": "integer"}], "description": "Number of bathroom of the property", "title": "Bathrooms"}, "has_solar_panels": {"description": "Whether the property has solar panels fitted", "title": "Has Solar Panels", "type": "boolean"}, "description": {"description": "Description of the property", "title": "Description", "type": "string"}, "neighborhood_description": {"description": "Description of the neighborhood", "title": "Neighborhood Description", "type": "string"}}, "required": ["neighborhood", "price", "bedrooms", "bathrooms", "has_solar_panels", "description", "neighborhood_description"], "title": "RealEstateListingModelOutput", "type": "object"}}, "properties": {"listings": {"items": {"$ref": "#/$defs/RealEstateListingModelOutput"}, "title": "Listings", "type": "array"}}, "required": ["listings"]}
```

We'll use OpenAI's gpt-4-turbo model as it has higher chances of following the instructions.

In [ ]:
llm = ChatOpenAI(
    model_name="gpt-4-turbo",
    temperature=0.2,  # Sacrificing reproducibility to give the model some leeway
    max_tokens=4000
)

We pipe the model's completion to the LangChain output parser to generate the Pydantic models of the listings.

In [ ]:
parsed_model_response = (llm | parser).invoke(prompt.format(num_listings=15))
parsed_model_response.listings
Out[ ]:
[RealEstateListingModelOutput(neighborhood='Maplewood Heights', price=450000, bedrooms=4, bathrooms=3, has_solar_panels=True, description='Charming 4-bedroom, 3-bathroom home in the serene Maplewood Heights, featuring a modern kitchen and a spacious living room with a fireplace. The exterior boasts a beautifully landscaped garden and a private backyard with a patio area perfect for entertaining. This eco-friendly home comes equipped with solar panels, reducing utility costs significantly.', neighborhood_description='Maplewood Heights is a family-friendly neighborhood known for its excellent schools, community parks, and active neighborhood association.'),
 RealEstateListingModelOutput(neighborhood='Old Town East', price=120000, bedrooms=2, bathrooms=1, has_solar_panels=False, description='Cozy 2-bedroom, 1-bathroom starter home in Old Town East, ideal for first-time buyers or investors. Needs some TLC but has great potential with hardwood floors and a compact, functional layout. The property includes a small front yard and a detached garage.', neighborhood_description='Old Town East is a lower-income area with a vibrant community spirit and easy access to public transportation.'),
 RealEstateListingModelOutput(neighborhood='Cedar Grove', price=750000, bedrooms=5, bathrooms=4, has_solar_panels=False, description='Luxurious 5-bedroom, 4-bathroom residence in prestigious Cedar Grove, featuring a gourmet kitchen with high-end appliances and a grand master suite with a spa-like bathroom. The meticulously maintained grounds include a pool, outdoor kitchen, and a three-car garage. Perfect for those who appreciate finer living and entertaining.', neighborhood_description='Cedar Grove is an affluent neighborhood known for its large, elegant homes and well-kept streets.'),
 RealEstateListingModelOutput(neighborhood='Pine Trail', price=300000, bedrooms=3, bathrooms=2.5, has_solar_panels=True, description="Modern 3-bedroom, 2.5-bathroom home in Pine Trail with eco-friendly features including solar panels and energy-efficient appliances. The open floor plan includes a large living area and a kitchen with a center island. Outdoors, there's a deck and a manageable yard, perfect for weekend relaxation.", neighborhood_description='Pine Trail is a growing community popular among young professionals and families, known for its sustainability initiatives and modern amenities.'),
 RealEstateListingModelOutput(neighborhood='Riverbend', price=200000, bedrooms=3, bathrooms=2, has_solar_panels=False, description='Affordable 3-bedroom, 2-bathroom home in the peaceful Riverbend neighborhood, featuring a spacious living room and a kitchen with ample storage. The property includes a large backyard with a shed and a covered porch. Ideal for families looking for a quiet, suburban lifestyle.', neighborhood_description='Riverbend is known for its safe streets and close-knit community, with several parks and a local elementary school.'),
 RealEstateListingModelOutput(neighborhood='Sunnyvale', price=980000, bedrooms=4, bathrooms=3.5, has_solar_panels=True, description='Stunning 4-bedroom, 3.5-bathroom home in Sunnyvale with luxurious finishes, a state-of-the-art kitchen, and a large home office. The property features a beautifully landscaped garden and a rooftop deck with solar panels. An ideal choice for those who value sustainability and upscale living.', neighborhood_description='Sunnyvale is an upscale neighborhood with a reputation for high-quality living, excellent schools, and a variety of recreational facilities.'),
 RealEstateListingModelOutput(neighborhood='Elmwood District', price=65000, bedrooms=1, bathrooms=1, has_solar_panels=False, description='Compact 1-bedroom, 1-bathroom fixer-upper in the Elmwood District, offering a unique opportunity for renovation and customization. The property includes a small yard and is located close to local amenities. Ideal for a DIY enthusiast or investor looking for a project.', neighborhood_description='The Elmwood District is a lower-income neighborhood undergoing revitalization, with potential for growth and increasing property values.'),
 RealEstateListingModelOutput(neighborhood='Brookside', price=550000, bedrooms=4, bathrooms=2.5, has_solar_panels=False, description='Beautifully maintained 4-bedroom, 2.5-bathroom family home in Brookside, featuring a formal dining room, a cozy fireplace, and a large kitchen with breakfast nook. The property boasts a spacious backyard with a play area and mature trees. A wonderful environment for family life and outdoor activities.', neighborhood_description='Brookside is a well-established, family-oriented neighborhood known for its tree-lined streets and friendly community atmosphere.'),
 RealEstateListingModelOutput(neighborhood='Highland Park', price=220000, bedrooms=3, bathrooms=1.5, has_solar_panels=False, description='Charming 3-bedroom, 1.5-bathroom home in Highland Park, perfect for those looking to put their personal touch on a property. The home features original woodwork and a large front porch. A great option for a handy homeowner or an investor.', neighborhood_description='Highland Park is a diverse, up-and-coming neighborhood appreciated for its historic homes and active community life.'),
 RealEstateListingModelOutput(neighborhood='Lakeside', price=850000, bedrooms=5, bathrooms=4, has_solar_panels=False, description='Expansive 5-bedroom, 4-bathroom lakefront property in Lakeside, offering breathtaking views and a private dock. The home includes multiple living spaces and a large deck for entertaining. Ideal for those seeking a tranquil retreat with ample space for guests.', neighborhood_description='Lakeside is a prestigious neighborhood known for its stunning waterfront homes and peaceful surroundings.'),
 RealEstateListingModelOutput(neighborhood='Greenfield', price=180000, bedrooms=2, bathrooms=1, has_solar_panels=False, description='Cozy 2-bedroom, 1-bathroom bungalow in Greenfield, featuring a welcoming front porch and a functional layout. The home is in need of some updates, making it a perfect project for those looking to add value. The large backyard offers plenty of space for expansion or gardening.', neighborhood_description='Greenfield is a budget-friendly neighborhood with a strong sense of community and easy access to local shops and parks.'),
 RealEstateListingModelOutput(neighborhood='Silver Lake', price=990000, bedrooms=4, bathrooms=3.5, has_solar_panels=True, description='Contemporary 4-bedroom, 3.5-bathroom home in Silver Lake, designed with sustainability in mind, featuring solar panels and modern architecture. The interior includes high ceilings, large windows, and a chef’s kitchen. Outside, the landscaped garden and patio area provide a perfect setting for relaxation and entertainment.', neighborhood_description='Silver Lake is a trendy neighborhood popular with artists and professionals, known for its eclectic shops, vibrant nightlife, and community events.'),
 RealEstateListingModelOutput(neighborhood='Willow Creek', price=230000, bedrooms=3, bathrooms=2, has_solar_panels=False, description='Affordable 3-bedroom, 2-bathroom home in Willow Creek, ideal for families or first-time home buyers. The home features a spacious living room and a large backyard with a deck. Located in a friendly community with good schools and parks nearby.', neighborhood_description='Willow Creek is a family-friendly neighborhood known for its affordable housing and active community life.'),
 RealEstateListingModelOutput(neighborhood='Meadowlands', price=320000, bedrooms=3, bathrooms=2.5, has_solar_panels=False, description='Well-appointed 3-bedroom, 2.5-bathroom home in Meadowlands, featuring a modern kitchen with stainless steel appliances and a master suite with a walk-in closet. The property includes a two-car garage and a fenced backyard. A great choice for those seeking a comfortable and convenient lifestyle.', neighborhood_description='Meadowlands is a quiet, suburban neighborhood with easy access to shopping centers and major highways.'),
 RealEstateListingModelOutput(neighborhood='Garden District', price=290000, bedrooms=3, bathrooms=2, has_solar_panels=False, description='Charming 3-bedroom, 2-bathroom cottage in the historic Garden District, featuring original hardwood floors and a cozy fireplace. The home includes a lovely front garden and a private backyard. Perfect for those who appreciate vintage charm and a central location.', neighborhood_description='The Garden District is renowned for its well-preserved historic homes and lush, mature gardens.'),
 RealEstateListingModelOutput(neighborhood='Vista Ridge', price=210000, bedrooms=2, bathrooms=1, has_solar_panels=False, description='Quaint 2-bedroom, 1-bathroom fixer-upper in Vista Ridge, offering a great opportunity for customization and improvement. The home sits on a large lot with potential for expansion or landscaping projects. An excellent investment for a visionary buyer.', neighborhood_description='Vista Ridge is a developing neighborhood with a mix of older homes and new constructions, appealing to both families and investors.')]

Let's save the generated real estate listings to avoid hitting the model multiple times.

In [ ]:
with open(data_dir / "listings.pickle", "wb") as f:
    pickle.dump(parsed_model_response.listings, f)

We generate the required Listings.txt as well:

In [ ]:
with open("Listings.txt", "w") as f:
    for listing in parsed_model_response.listings:
        f.write(listing.model_dump_json(indent=2))
        f.write("\n\n")

Read the listings back.

In [ ]:
with open(data_dir / "listings.pickle", "rb") as f:
    listings = pickle.load(f)

Generating Real Estate Listings Images¶

We want to increase the usability of our recommendation app, so we'll use OpenAI's DALL-e. We're adding specific hints to the prompt to generate photorealistic images.

In [ ]:
client = openai.OpenAI()
In [ ]:
listings_with_image = []

for i, listing in enumerate(listings):
    display(Markdown(f"Generating image for listing with description: _'{listing.description}'_...."))

    dalle2_response = client.images.generate(
        model="dall-e-2",
        prompt=f"Photo of {listing.description}. 1/100s, ISO 100, Daylight.",
        size="512x512",
        quality="standard",
        n=1,
    )

    response = requests.get(dalle2_response.data[0].url)
    response.raise_for_status()

    listings_with_image.append(
        RealEstateListing(
            **listing.model_dump(),
            image_bytes=response.content,
        )
    )

    image = Image.open(BytesIO(response.content))

    display(image)

Generating image for listing with description: 'Charming 4-bedroom, 3-bathroom home in the serene Maplewood Heights, featuring a modern kitchen and a spacious living room with a fireplace. The exterior boasts a beautifully landscaped garden and a private backyard with a patio area perfect for entertaining. This eco-friendly home comes equipped with solar panels, reducing utility costs significantly.'....

No description has been provided for this image

Generating image for listing with description: 'Cozy 2-bedroom, 1-bathroom starter home in Old Town East, ideal for first-time buyers or investors. Needs some TLC but has great potential with hardwood floors and a compact, functional layout. The property includes a small front yard and a detached garage.'....

No description has been provided for this image

Generating image for listing with description: 'Luxurious 5-bedroom, 4-bathroom residence in prestigious Cedar Grove, featuring a gourmet kitchen with high-end appliances and a grand master suite with a spa-like bathroom. The meticulously maintained grounds include a pool, outdoor kitchen, and a three-car garage. Perfect for those who appreciate finer living and entertaining.'....

No description has been provided for this image

Generating image for listing with description: 'Modern 3-bedroom, 2.5-bathroom home in Pine Trail with eco-friendly features including solar panels and energy-efficient appliances. The open floor plan includes a large living area and a kitchen with a center island. Outdoors, there's a deck and a manageable yard, perfect for weekend relaxation.'....

No description has been provided for this image

Generating image for listing with description: 'Affordable 3-bedroom, 2-bathroom home in the peaceful Riverbend neighborhood, featuring a spacious living room and a kitchen with ample storage. The property includes a large backyard with a shed and a covered porch. Ideal for families looking for a quiet, suburban lifestyle.'....

No description has been provided for this image

Generating image for listing with description: 'Stunning 4-bedroom, 3.5-bathroom home in Sunnyvale with luxurious finishes, a state-of-the-art kitchen, and a large home office. The property features a beautifully landscaped garden and a rooftop deck with solar panels. An ideal choice for those who value sustainability and upscale living.'....

No description has been provided for this image

Generating image for listing with description: 'Compact 1-bedroom, 1-bathroom fixer-upper in the Elmwood District, offering a unique opportunity for renovation and customization. The property includes a small yard and is located close to local amenities. Ideal for a DIY enthusiast or investor looking for a project.'....

No description has been provided for this image

Generating image for listing with description: 'Beautifully maintained 4-bedroom, 2.5-bathroom family home in Brookside, featuring a formal dining room, a cozy fireplace, and a large kitchen with breakfast nook. The property boasts a spacious backyard with a play area and mature trees. A wonderful environment for family life and outdoor activities.'....

No description has been provided for this image

Generating image for listing with description: 'Charming 3-bedroom, 1.5-bathroom home in Highland Park, perfect for those looking to put their personal touch on a property. The home features original woodwork and a large front porch. A great option for a handy homeowner or an investor.'....

No description has been provided for this image

Generating image for listing with description: 'Expansive 5-bedroom, 4-bathroom lakefront property in Lakeside, offering breathtaking views and a private dock. The home includes multiple living spaces and a large deck for entertaining. Ideal for those seeking a tranquil retreat with ample space for guests.'....

No description has been provided for this image

Generating image for listing with description: 'Cozy 2-bedroom, 1-bathroom bungalow in Greenfield, featuring a welcoming front porch and a functional layout. The home is in need of some updates, making it a perfect project for those looking to add value. The large backyard offers plenty of space for expansion or gardening.'....

No description has been provided for this image

Generating image for listing with description: 'Contemporary 4-bedroom, 3.5-bathroom home in Silver Lake, designed with sustainability in mind, featuring solar panels and modern architecture. The interior includes high ceilings, large windows, and a chef’s kitchen. Outside, the landscaped garden and patio area provide a perfect setting for relaxation and entertainment.'....

No description has been provided for this image

Generating image for listing with description: 'Affordable 3-bedroom, 2-bathroom home in Willow Creek, ideal for families or first-time home buyers. The home features a spacious living room and a large backyard with a deck. Located in a friendly community with good schools and parks nearby.'....

No description has been provided for this image

Generating image for listing with description: 'Well-appointed 3-bedroom, 2.5-bathroom home in Meadowlands, featuring a modern kitchen with stainless steel appliances and a master suite with a walk-in closet. The property includes a two-car garage and a fenced backyard. A great choice for those seeking a comfortable and convenient lifestyle.'....

No description has been provided for this image

Generating image for listing with description: 'Charming 3-bedroom, 2-bathroom cottage in the historic Garden District, featuring original hardwood floors and a cozy fireplace. The home includes a lovely front garden and a private backyard. Perfect for those who appreciate vintage charm and a central location.'....

No description has been provided for this image

Generating image for listing with description: 'Quaint 2-bedroom, 1-bathroom fixer-upper in Vista Ridge, offering a great opportunity for customization and improvement. The home sits on a large lot with potential for expansion or landscaping projects. An excellent investment for a visionary buyer.'....

No description has been provided for this image

We save the results one more time, to avoid hitting the model multiple times.

In [ ]:
with open(data_dir / "listings_with_image.pickle", "wb") as f:
    pickle.dump(listings_with_image, f)

Read the listings back

In [ ]:
with open(data_dir / "listings_with_image.pickle", "rb") as f:
    listings_with_image = pickle.load(f)

Storing Listings in a Vector Database¶

Vector Database Setup¶

We initialize the vector database, re-creating We create the listings table using the RealEstateListingLanceRecord schema from the models module.

In [ ]:
db = get_db()
init_db(db)
In [ ]:
table = get_listings_table(db)

Generating and Storing Embeddings¶

We're going to use HuggingFace's CLIP models to generate embeddings for the listing and image combination.

In [ ]:
clip_model = "openai/clip-vit-large-patch14"

model = CLIPModel.from_pretrained(clip_model).to(device)
processor = CLIPProcessor.from_pretrained(clip_model)
tokenizer = AutoTokenizer.from_pretrained(clip_model)
In [ ]:
def get_listing_embeddings(listing: RealEstateListing) -> torch.Tensor:
    processor_output = processor(
        text=[listing.description + listing.neighborhood_description],
        images=listing.image_as_pil,
        return_tensors="pt",
        padding=True,
        truncation=True
    )
    image = processor_output["pixel_values"].to(device)
    image_embeddings = model.get_image_features(image)

    return image_embeddings[0].cpu()
In [ ]:
table.add([
    RealEstateListingLanceRecord(
        **listing.model_dump(),
        vector=get_listing_embeddings(listing).detach().numpy()
    )
    for listing in listings_with_image
])

Querying the Vector Database¶

In [ ]:
inputs = tokenizer("Affordable house with backyard", padding=True, truncation=True, return_tensors="pt").to(device)
text_features = model.get_text_features(**inputs)[0].cpu().detach().numpy()
In [ ]:
Markdown(
    "\n".join(
        f"* _{listing.description}_" for listing in table.search(text_features).limit(3).to_pydantic(RealEstateListingLanceRecord)
    )
)
Out[ ]:
  • Affordable 3-bedroom, 2-bathroom home in the peaceful Riverbend neighborhood, featuring a spacious living room and a kitchen with ample storage. The property includes a large backyard with a shed and a covered porch. Ideal for families looking for a quiet, suburban lifestyle.
  • Luxurious 5-bedroom, 4-bathroom residence in prestigious Cedar Grove, featuring a gourmet kitchen with high-end appliances and a grand master suite with a spa-like bathroom. The meticulously maintained grounds include a pool, outdoor kitchen, and a three-car garage. Perfect for those who appreciate finer living and entertaining.
  • Affordable 3-bedroom, 2-bathroom home in Willow Creek, ideal for families or first-time home buyers. The home features a spacious living room and a large backyard with a deck. Located in a friendly community with good schools and parks nearby.